var Utils = (function (exports) {
    'use strict';

    const JsonUtil = {
        parse: function (str) {
            return JSON.parse(str);
        },
        stringify: function (obj) {
            return JSON.stringify(obj);
        }
    };

    const DateUtil = {
        /**
         * @param weekdayNumber  0,1,3,4,5,6
         * @returns {string} 星期天/星期一/星期二/星期三/星期四/星期五/星期六
         */
        weekdayNumber2Str: function (weekdayNumber) {
            if (weekdayNumber == 0) {
                return '星期天'
            } else if (weekdayNumber == 1) {
                return '星期一'
            } else if (weekdayNumber == 2) {
                return '星期二'
            } else if (weekdayNumber == 3) {
                return '星期三'
            } else if (weekdayNumber == 4) {
                return '星期四'
            } else if (weekdayNumber == 5) {
                return '星期五'
            } else if (weekdayNumber == 6) {
                return '星期六'
            } else {
                return '星期undefined'
            }
        },
        /**
         * @param date  Date
         * @returns {string} 例如： 公历时间 2025-01-07 => 甲辰年腊月初八
         */
        date2nlStr: function (date) {
            // 获取本地化日期字符串，并去掉时分秒部分
            let formattedDate = date.toLocaleString('zh-CN-u-ca-chinese', {hour12: false, timeZone: 'Asia/Shanghai'})
                .split(' ')[0] // 只保留年月日部分
                .replace(/(\d+)\s*?/, (_, y) => {
                    // 干支纪年法替换年份
                    return "甲乙丙丁戊己庚辛壬癸".charAt((y - 4) % 10) +
                        "子丑寅卯辰巳午未申酉戌亥".charAt((y - 4) % 12);
                });
            formattedDate = formattedDate.replace(/(\d+)\s*?/, (_, d) => {
                if (d == '1') {
                    return "初一"
                } else if (d == '2') {
                    return "初二";
                } else if (d == '3') {
                    return "初三";
                } else if (d == '4') {
                    return "初四";
                } else if (d == '5') {
                    return "初五";
                } else if (d == '6') {
                    return "初六";
                } else if (d == '7') {
                    return "初七";
                } else if (d == '8') {
                    return "初八";
                } else if (d == '9') {
                    return "初九";
                } else if (d == '10') {
                    return "初十";
                } else if (d == '11') {
                    return "十一";
                } else if (d == '12') {
                    return "十二";
                } else if (d == '13') {
                    return "十三";
                } else if (d == '14') {
                    return "十四";
                } else if (d == '15') {
                    return "十五";
                } else if (d == '16') {
                    return "十六";
                } else if (d == '17') {
                    return "十七";
                } else if (d == '18') {
                    return "十八";
                } else if (d == '19') {
                    return "十九";
                } else if (d == '20') {
                    return "二十";
                } else if (d == '21') {
                    return "廿一";
                } else if (d == '22') {
                    return "廿二";
                } else if (d == '23') {
                    return "廿三";
                } else if (d == '24') {
                    return "廿四";
                } else if (d == '25') {
                    return "廿五";
                } else if (d == '26') {
                    return "廿六";
                } else if (d == '27') {
                    return "廿七";
                } else if (d == '28') {
                    return "廿八";
                } else if (d == '29') {
                    return "廿九";
                } else if (d == '30') {
                    return "三十";
                } else if (d == '31') {
                    return "卅一";
                }
                return "";
            })
            return formattedDate;
        },

        getNlJieJiaRiName: function (date) {
            let nldateStr = date.toLocaleString('zh-CN-u-ca-chinese', {
                hour12: false,
                timeZone: 'Asia/Shanghai'
            }).split(' ')[0];
            let nIndex = nldateStr.indexOf('年');
            let yIndex = nldateStr.indexOf('月');
            let ly = nldateStr.substring(0, nIndex);
            let lmGet = function (lmName) {
                if (lmName == "腊月") {
                    return 12;
                } else if (lmName == "十一月") {
                    return 11;
                } else if (lmName == "十月") {
                    return 10;
                } else if (lmName == "九月") {
                    return 9;
                } else if (lmName == "八月") {
                    return 8;
                } else if (lmName == "七月") {
                    return 7;
                } else if (lmName == "六月") {
                    return 6;
                } else if (lmName == "五月") {
                    return 5;
                } else if (lmName == "四月") {
                    return 4;
                } else if (lmName == "三月") {
                    return 3;
                } else if (lmName == "二月") {
                    return 2;
                } else if (lmName == "正月") {
                    return 1;
                } else {
                    return 0;
                }
            }
            let lm = lmGet(nldateStr.substring(nIndex + 1, yIndex + 1));
            let ld = nldateStr.substring(yIndex + 1)

            // 初始化农历节日数组
            const lunarFestival = new Array(
                "0101 春节",
                "0107 人胜节",
                "0115 元宵节",
                "0120 天穿节",
                "0125 天仓节",
                "0201 中和节",
                "0202 春龙节(龙抬头)",
                "0212 花朝节",
                "0303 上巳节",
                "0408 浴佛节",
                "0505 端午节",
                "0606 晒衣节",
                "0707 乞巧节(七夕)",
                "0715 中元节",
                "0801 天医节",
                "0815 中秋节",
                "0909 重阳节",
                "1001 寒衣节",
                "1015 下元节",
                "1208 腊八节",
                "1224 祭灶节(小年)"
            );
            // 农历查询表
            const lunarYearArr = new Array(
                0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,//1900-1909
                0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,//1910-1919
                0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,//1920-1929
                0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,//1930-1939
                0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,//1940-1949
                0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0,//1950-1959
                0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,//1960-1969
                0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6,//1970-1979
                0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,//1980-1989
                0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,//1990-1999
                0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,//2000-2009
                0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,//2010-2019
                0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,//2020-2029
                0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,//2030-2039
                0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0,//2040-2049
                0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0,//2050-2059
                0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4,//2060-2069
                0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0,//2070-2079
                0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160,//2080-2089
                0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252,//2090-2099
                0x0d520 //2100
            );
            const hasLeapMonth = function (ly) {
                //农历低四位不等于0即为存在闰月
                //存在闰月即返回闰月所在月份
                if (ly & 0x0000f) {
                    return ly & 0x0000f
                } else {
                    return false
                }
            }
            const leapMonthDays = function (ly) {
                //农历高四位等于0即为闰小月29天, 不等于0(等于1)即为闰大月30天
                //存在闰月即返回闰月天数
                if (hasLeapMonth(ly)) {
                    return (ly & 0xf0000) ? 30 : 29
                } else {
                    return 0
                }
            }
            const lunarYearMonths = function (ly) {
                //从高位第16位(1月)起向右移至低位第5位(12月)添加数组每项
                let monthArr = [];
                for (let i = 0x8000; i > 0x8; i >>= 1) {
                    monthArr.push((ly & i) ? 30 : 29);
                }
                //考虑是否有闰月天数
                if (hasLeapMonth(ly)) {
                    monthArr.splice(hasLeapMonth(ly), 0, leapMonthDays(ly));
                }
                return monthArr
            }
            // 基准年
            const BENCHMARK_YEAR = 1900;
            // 计算农历节日
            // ly lm ld 为农历年月日
            let lunar = null;
            lunarFestival.forEach((item, index) => {
                let str = item.split(" ");
                if (str[0] == `${lm < 10 ? "0" + lm : lm}${ld < 10 ? "0" + ld : ld}`) {
                    lunar = str[1];
                }
                //部分节日需要手动计算例如春节前一天除夕，清明前一天寒食节等等
                //考虑到闰正月和闰腊月计算相对复杂这里仅做粗略计算，严谨请参照(平气法已过时)定气法具体百度搜索相关资料做调整
                let lymArr = lunarYearMonths(lunarYearArr[ly - BENCHMARK_YEAR]);
                if (`${lm}${ld}` == `12${lymArr[lymArr.length - 1]}`) {
                    lunar = "除夕";
                }
            })
            return lunar;
        },

        getNlJieQi: function (date) {
            let solarTerm = new Array("小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至");
            let sTermInfo = new Array(0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758);
            let y = date.getFullYear();
            let mon = date.getMonth();
            let d = date.getDate();
            let solarTerms = "";
            let sotmp1 = new Date((31556925974.7 * (y - 1900) + sTermInfo[mon * 2 + 1] * 60000) + Date.UTC(1900, 0, 6, 2, 5));
            let sotmp2 = sotmp1.getUTCDate(); //根据世界时返回一个月 (UTC) 中的某一天
            if (sotmp2 == d) {
                solarTerms = solarTerm[mon * 2 + 1];
                return solarTerms;
            }
            sotmp1 = new Date((31556925974.7 * (y - 1900) + sTermInfo[mon * 2] * 60000) + Date.UTC(1900, 0, 6, 2, 5));
            sotmp2 = sotmp1.getUTCDate();
            if (sotmp2 == d) {
                solarTerms = solarTerm[mon * 2];
                return solarTerms;
            }
            return "";
        },

        getYlZJieJiaRiName: function (date) {
            //哪一月第几周的星期几 节假日
            let wFtv = new Array(
                "0420 复活节", //在每年春分月圆之后第一个星期日 耶穌受難節是復活節前一个星期五
                "0520 母亲节", //每年5月的第二个星期日
                "0950 世界心脏日", //最后一个星期日
                "0630 父亲节", //每年公历6月的第三个星期日
                "1144 感恩节", //1月的第四个星期四庆祝感恩节
            );

            let padZero = (num) => String(num).padStart(2, '0');

            let month = padZero(date.getMonth() + 1); // 月份从0开始，所以需要加1
            let day = date.getDate(); //月内第几天从1开始
            let weekDay = date.getDay(); //星期几 从0开始-6
            let weekDayNum = weekDay == 0 ? 7 : weekDay;
            let dateZStr = `${month}${Math.floor(((day - 1) / 7) + 1)}${weekDay}`;
            for (let i = 0; i < wFtv.length; i++) {
                if (wFtv[i].startsWith(dateZStr)) {
                    return wFtv[i].split(" ")[1]
                }
            }
            return ""
        },

        getYlJieJiaRiName: function (date) {
            //MM-dd 公历
            let sFtv = [
                {
                    monthDay: "01-01",
                    name: "元旦"
                },
                {
                    monthDay: "02-14",
                    name: "情人节"
                },
                {
                    monthDay: "03-07",
                    name: "女生节"
                },
                {
                    monthDay: "03-08",
                    name: "妇女节"
                },
                {
                    monthDay: "03-12",
                    name: "植树节"
                },
                {
                    monthDay: "04-01",
                    name: "愚人节"
                },
                {
                    monthDay: "04-04",
                    name: "清明节"
                },
                {
                    monthDay: "05-01",
                    name: "劳动节"
                },
                {
                    monthDay: "05-04",
                    name: "青年节"
                },
                {
                    monthDay: "06-01",
                    name: "儿童节"
                },
                {
                    monthDay: "07-01",
                    name: "建党节"
                },
                {
                    monthDay: "08-01",
                    name: "建军节"
                },
                {
                    monthDay: "09-10",
                    name: "教师节"
                },
                {
                    monthDay: "10-01",
                    name: "国庆节"
                },
                {
                    monthDay: "10-31",
                    name: "万圣节"
                },
                {
                    monthDay: "12-24",
                    name: "平安夜"
                },
                {
                    monthDay: "12-25",
                    name: "圣诞节"
                }
            ];
            let monethDayStr = this.date2MonthDayStr(date);
            for (let i = 0; i < sFtv.length; i++) {
                if (sFtv[i].monthDay == monethDayStr) {
                    return sFtv[i].name;
                }
            }
            return "";
        },

        /**
         * @param date
         * @return yyyy-MM-dd HH:mm:ss
         */
        date2DateTimeStr: function (date) {
            let padZero = (num) => String(num).padStart(2, '0');

            let year = date.getFullYear();
            let month = padZero(date.getMonth() + 1); // 月份从0开始，所以需要加1
            let day = padZero(date.getDate());
            let hours = padZero(date.getHours());
            let minutes = padZero(date.getMinutes());
            let seconds = padZero(date.getSeconds());

            return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
        },
        /**
         * @param date
         * @return yyyy-MM-dd
         */
        date2DateStr: function (date) {
            let padZero = (num) => String(num).padStart(2, '0');

            let year = date.getFullYear();
            let month = padZero(date.getMonth() + 1); // 月份从0开始，所以需要加1
            let day = padZero(date.getDate());

            return `${year}-${month}-${day}`;
        },
        /**
         * @param date
         * @return MM-dd
         */
        date2MonthDayStr: function (date) {
            let padZero = (num) => String(num).padStart(2, '0');

            let month = padZero(date.getMonth() + 1); // 月份从0开始，所以需要加1
            let day = padZero(date.getDate());

            return `${month}-${day}`;
        }
    }

    const ArrayUtil = {
        addOne: function (arr, value) {
            arr.push(value);
        },
        addBatch: function (arr, valueAry) {
            valueAry.forEach(function (value) {
                arr.push(value);
            })
        },
        deleteOne: function (arr, value) {
            let deleteIndex = null;
            for (let i = 0; i < arr.length; i++) {
                if (value == arr[i]) {
                    deleteIndex = i;
                    break;
                }
            }
            arr.splice(deleteIndex, 1);
        },
        clearAll: function (arr) {
            let length = arr.length;
            if (length == 0) {
                return;
            }
            arr.splice(0, length);
        }
    }

    const ObjectUtil = {
        /**
         * for (const [key, value] of ObjectUtil.entries(obj))
         * @param obj
         * @returns array {[string, unknown][]}
         *
         * objetest = {
         *     a: "111",
         *     b: 222,
         *     c: function (v1){
         *         return v1;
         *     },
         *     d: function (){
         *         this.a = "333"
         *     }
         * }
         */
        entries: function (obj) {
            return Object.entries(obj);
        },
        /**
         * @param obj
         * @returns {[string, unknown][]}
         *
         * objetest = {
         *     a: "111",
         *     b: 222
         * }
         */
        entriesNoFunction: function (obj) {
            return Object.entries(obj).filter(([key, value]) => typeof value !== 'function');
        },
        getObjTypeName: function (obj) {
            return Object.prototype.toString.call(obj)
        }
    }

    const BrowserLocalStorageUtil = {
        setItem: function (key, value) {
            if (typeof value == "object" || value instanceof Array) {
                localStorage.setItem(key, JsonUtil.stringify(value));
            } else {
                localStorage.setItem(key, value);
            }
        },
        getItem: function (key) {
            return localStorage.getItem(key);
        },
        getItemObjOrArray: function (key) {
            return JsonUtil.parse(localStorage.getItem(key));
        }
    }

    const BrowserIndexDbUtil = {/** 暂未实现 **/}

    const AxiosUtil = {
        //第1个参数axios需引入第三方JS
        createAxiosInstance: function (axios, config, interceptorsRequest, interceptorsRequestErr, interceptorsResponse, interceptorsResponseErr) {
            config = config || {}
            let defaultConfig = {
                ...config,
                baseURL: config.baseURL || window.location.origin,
                timeout: config.timeout || 5000,
                withCredentials: config.withCredentials || false
            }
            const axiosInstance = axios.create(defaultConfig);
            axiosInstance.interceptors.request.use(
                interceptorsRequest || function (config) {
                    return config;
                },
                interceptorsRequestErr || function (error) {
                    return Promise.reject(error);
                }
            );
            axiosInstance.interceptors.response.use(
                interceptorsResponse || function (response) {
                    // 2xx 范围内的状态码都会触发该函数。
                    return response;
                },
                interceptorsResponseErr || function (error) {
                    // 超出 2xx 范围的状态码都会触发该函数。
                    return Promise.reject(error);
                }
            );
            return axiosInstance;
        }
    }

    const PromiseUtil = {
        //PromiseUtil.sleep(3000).then(() => {异步3秒后执行的逻辑})
        sleep: function (ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }
    }

    const FileUtil = {
        getFileSize: function (file) {
            return file.size;
        },
        getFileName: function (file) {
            return file.name;
        },
        getFileType: function (file) {
            return file.type;
        },
        printFileInfo: function (file) {
            console.log("名称", file.name, "类型", file.type, "字节" , file.size);
        },
        readFileAsString: function (file, resCall) {
            const reader = new FileReader();
            reader.onload = (e) => {
                const fileContent = e.target.result;
                resCall(fileContent);
            };
            reader.readAsText(file);
        }
    }

    exports.JsonUtil = JsonUtil;
    exports.DateUtil = DateUtil;
    exports.ArrayUtil = ArrayUtil;
    exports.BrowserLocalStorageUtil = BrowserLocalStorageUtil;
    exports.BrowserIndexDbUtil = BrowserIndexDbUtil;
    exports.ObjectUtil = ObjectUtil;
    exports.AxiosUtil = AxiosUtil;
    exports.PromiseUtil = PromiseUtil;
    exports.FileUtil = FileUtil;
    return exports;
})({});

const {
    JsonUtil,
    DateUtil,
    ArrayUtil,
    BrowserLocalStorageUtil,
    BrowserIndexDbUtil,
    ObjectUtil,
    AxiosUtil,
    PromiseUtil,
    FileUtil
} = Utils;